namespace Plugins.Engine
{
    using System;
    using System.Diagnostics.CodeAnalysis;
    using System.Globalization;
    using Plugins.Interfaces;
    using Plugins.Library;
    using Plugins.Serializer;

    [Serializable]
    public class PluginPropertyConverter : 
        IPluginPropertyConverter<string>, 
        IPluginPropertyConverter<bool>, 
        IPluginPropertyConverter<sbyte>,
        IPluginPropertyConverter<byte>,
        IPluginPropertyConverter<object>,
        IPluginPropertyConverter<char>, 
        IPluginPropertyConverter<decimal>, 
        IPluginPropertyConverter<double>, 
        IPluginPropertyConverter<float>, 
        IPluginPropertyConverter<short>, 
        IPluginPropertyConverter<int>, 
        IPluginPropertyConverter<long>, 
        IPluginPropertyConverter<ushort>, 
        IPluginPropertyConverter<uint>, 
        IPluginPropertyConverter<ulong>,
        IPluginPropertyConverter<Guid>,
        IPluginPropertyConverter<TimeSpan>, 
        IPluginPropertyConverter<DateTime>, 
        IPluginPropertyConverter<DateTimeOffset>
    {
        private static readonly object _instance = new PluginPropertyConverter();
        private static readonly IPluginStringSerializer<string> _stringSerializer = new PluginBase64StringSerializer<string>();
        private static readonly IPluginBinarySerializer<object> _objectSerializer = new PluginBinarySerializer<object>();

        [SuppressMessage("Microsoft.Design", "CA1004")]
        public static T ConvertFromString<T>(string value)
        {
            return ConvertFromString<T>(_instance as IPluginPropertyConverter<T>, value);
        }

        [SuppressMessage("Microsoft.Design", "CA1031")]
        public static T ConvertFromString<T>(IPluginPropertyConverter<T> converter, string value)
        {
            try
            {
                if (converter == null)
                {
                    converter = _instance as IPluginPropertyConverter<T>;
                }
                if (converter != null)
                {
                    return converter.ConvertFromString(value);
                }
                else
                {
                    IPluginPropertyConverter<object> serializer = _instance as IPluginPropertyConverter<object>;
                    return (T)serializer.ConvertFromString(value);
                }
            }
            catch (Exception ex)
            {
                PluginLog.WriteErrorSync(ex);
            }
            return default(T);
        }

        public static string ConvertToString<T>(T value)
        {
            return ConvertToString<T>(_instance as IPluginPropertyConverter<T>, value);
        }

        [SuppressMessage("Microsoft.Design", "CA1031")]
        public static string ConvertToString<T>(IPluginPropertyConverter<T> converter, T value)
        {
            try
            {
                if (converter == null)
                {
                    converter = _instance as IPluginPropertyConverter<T>;
                }
                if (converter != null)
                {
                    return converter.ConvertToString(value);
                }
                else
                {
                    IPluginPropertyConverter<object> serializer = _instance as IPluginPropertyConverter<object>;
                    return serializer.ConvertToString(value);
                }
            }
            catch (Exception ex)
            {
                PluginLog.WriteErrorSync(ex);
            }
            return null;
        }


        object IPluginPropertyConverter<object>.ConvertFromString(string s)
        {
            return _objectSerializer.Deserialize(Convert.FromBase64String(s));
        }

        string IPluginPropertyConverter<object>.ConvertToString(object value)
        {
            return Convert.ToBase64String(_objectSerializer.Serialize(value));
        }    
        
        bool IPluginPropertyConverter<bool>.ConvertFromString(string s)
        {
            return bool.Parse(s);
        }

        string IPluginPropertyConverter<bool>.ConvertToString(bool value)
        {
            return value.ToString(CultureInfo.InvariantCulture);
        }

        byte IPluginPropertyConverter<byte>.ConvertFromString(string s)
        {
            return byte.Parse(s, CultureInfo.InvariantCulture);
        }

        string IPluginPropertyConverter<byte>.ConvertToString(byte value)
        {
            return value.ToString(CultureInfo.InvariantCulture);
        }


        char IPluginPropertyConverter<char>.ConvertFromString(string s)
        {
            return char.Parse(s);
        }

        string IPluginPropertyConverter<char>.ConvertToString(char value)
        {
            return value.ToString(CultureInfo.InvariantCulture);
        }

        DateTime IPluginPropertyConverter<DateTime>.ConvertFromString(string s)
        {
            return DateTime.Parse(s, CultureInfo.InvariantCulture);
        }

        string IPluginPropertyConverter<DateTime>.ConvertToString(DateTime value)
        {
            return value.ToString(CultureInfo.InvariantCulture);
        }

        DateTimeOffset IPluginPropertyConverter<DateTimeOffset>.ConvertFromString(string s)
        {
            return DateTimeOffset.Parse(s, CultureInfo.InvariantCulture);
        }

        string IPluginPropertyConverter<DateTimeOffset>.ConvertToString(DateTimeOffset value)
        {
            return value.ToString(CultureInfo.InvariantCulture);
        }

        decimal IPluginPropertyConverter<decimal>.ConvertFromString(string s)
        {
            return decimal.Parse(s, CultureInfo.InvariantCulture);
        }

        string IPluginPropertyConverter<decimal>.ConvertToString(decimal value)
        {
            return value.ToString(CultureInfo.InvariantCulture);
        }

        double IPluginPropertyConverter<double>.ConvertFromString(string s)
        {
            return double.Parse(s, CultureInfo.InvariantCulture);
        }

        string IPluginPropertyConverter<double>.ConvertToString(double value)
        {
            return value.ToString(CultureInfo.InvariantCulture);
        }

        short IPluginPropertyConverter<short>.ConvertFromString(string s)
        {
            return short.Parse(s, CultureInfo.InvariantCulture);
        }

        string IPluginPropertyConverter<short>.ConvertToString(short value)
        {
            return value.ToString(CultureInfo.InvariantCulture);
        }

        int IPluginPropertyConverter<int>.ConvertFromString(string s)
        {
            return int.Parse(s, CultureInfo.InvariantCulture);
        }

        string IPluginPropertyConverter<int>.ConvertToString(int value)
        {
            return value.ToString(CultureInfo.InvariantCulture);
        }

        long IPluginPropertyConverter<long>.ConvertFromString(string s)
        {
            return long.Parse(s, CultureInfo.InvariantCulture);
        }

        string IPluginPropertyConverter<long>.ConvertToString(long value)
        {
            return value.ToString(CultureInfo.InvariantCulture);
        }

        sbyte IPluginPropertyConverter<sbyte>.ConvertFromString(string s)
        {
            return sbyte.Parse(s, CultureInfo.InvariantCulture);
        }

        string IPluginPropertyConverter<sbyte>.ConvertToString(sbyte value)
        {
            return value.ToString(CultureInfo.InvariantCulture);
        }

        float IPluginPropertyConverter<float>.ConvertFromString(string s)
        {
            return float.Parse(s, CultureInfo.InvariantCulture);
        }

        string IPluginPropertyConverter<float>.ConvertToString(float value)
        {
            return value.ToString(CultureInfo.InvariantCulture);
        }

        string IPluginPropertyConverter<string>.ConvertFromString(string s)
        {
            return _stringSerializer.Deserialize(s);
        }

        string IPluginPropertyConverter<string>.ConvertToString(string value)
        {
            return _stringSerializer.Serialize(value);
        }

        TimeSpan IPluginPropertyConverter<TimeSpan>.ConvertFromString(string s)
        {
            return TimeSpan.Parse(s);
        }

        string IPluginPropertyConverter<TimeSpan>.ConvertToString(TimeSpan value)
        {
            return value.ToString();
        }

        ushort IPluginPropertyConverter<ushort>.ConvertFromString(string s)
        {
            return ushort.Parse(s, CultureInfo.InvariantCulture);
        }

        string IPluginPropertyConverter<ushort>.ConvertToString(ushort value)
        {
            return value.ToString(CultureInfo.InvariantCulture);
        }

        uint IPluginPropertyConverter<uint>.ConvertFromString(string s)
        {
            return uint.Parse(s, CultureInfo.InvariantCulture);
        }

        string IPluginPropertyConverter<uint>.ConvertToString(uint value)
        {
            return value.ToString(CultureInfo.InvariantCulture);
        }

        ulong IPluginPropertyConverter<ulong>.ConvertFromString(string s)
        {
            return ulong.Parse(s, CultureInfo.InvariantCulture);
        }

        string IPluginPropertyConverter<ulong>.ConvertToString(ulong value)
        {
            return value.ToString(CultureInfo.InvariantCulture);
        }

        Guid IPluginPropertyConverter<Guid>.ConvertFromString(string s)
        {
            return new Guid(s);
        }

        string IPluginPropertyConverter<Guid>.ConvertToString(Guid value)
        {
            return value.ToString(null, CultureInfo.InvariantCulture);
        }
    }
}

